home *** CD-ROM | disk | FTP | other *** search
- ;======================================================================
- ; SETMODE is a resident program which allows you to set the video mode
- ; and the communication port protocol. PC Magazine July, 1988
- ;----------------------------------------------------------------------
- ; BIOS_SEG is the ROM-BIOS data area
- ;----------------------------------------------------------------------
- BIOS_SEG SEGMENT AT 0040H
- ORG 0010H
- EQUIP_FLAG DW ?
- ORG 0049H
- CRT_MODE DB ?
- COLUMNS DB ? ;Current number of columns
- ORG 0050H
- CURSOR_POSN DW 8 DUP(?) ;Current cursor location
- ORG 0062H
- ACTIVE_PAGE DB ? ;Active page for CGA and EGA
- ORG 0084H
- ROWS DB ? ;Last row number for EGA
- DW ?
- EGA_INFO DB ?
- BIOS_SEG ENDS
-
- CSEG SEGMENT
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
- ORG 0100H ;Beginning for .COM programs
- START: JMP INITIALIZE ;Initialization code is at end
-
- ;----------------------------------------------------------------------
- ; Data area used by this program
- ;----------------------------------------------------------------------
- HOTKEY EQU 32H ;Scan code for "M" key
- SHIFT_MASK EQU 00001000B ;Mask for ALT key
- CR EQU 13
- LF EQU 10
-
- COPYRIGHT DB "SETMODE 1.0 (c) 1988 Ziff Communications Co."
- DB CR,LF,"PC Magazine ",254," Tom Kihlken"
- DB CR,LF,"Hotkey is Alt-M$",1AH
- INSTALLED_MSG DB CR,LF,"Already Installed$"
-
- WINDOW_TEXT DB 2, 1,"SETMODE 1.0 "
- DB 24,32,25,32,26,32,27," + - <CR> Esc",0
- DB 4, 4,"COMMUNICATION PORTS",0
- DB 2, 5,"Port:",0
- DB 16,5,"1",0
- DB 23,5,"2",0
- DB 30,5,"3",0
- DB 37,5,"4",0
- DB 2, 6,"Bps:",0
- DB 2, 7,"Parity:",0
- DB 2, 8,"Data bits:",0
- DB 2, 9,"Stop Bits:",0
- DB 2,10,"DSR:",0
- DB 4,13,"DISPLAY",0
- DB 4,14,"Mode:",0
- DB 2,15,"0 1 2 3 4 5 6 7 13 14 15 16 17 18 19",0,0
-
- COUNTER1 DB ?
- COUNTER2 DB ?
- BUSY_FLAG DB 0
- COLORS LABEL WORD
- NORMAL DB ?
- INVERSE DB ?
- OLDINT09 DD ?
- LEFT_SIDE DB ?
- MODE_SELECT DB ?
- GRAPH_TEXT DB ?
- ITEM_SELECT DB 0
- PORT_SELECT DB 0
- PORT_ADDRESS DW ?
- ADAPTER_FLAGS DB ?
- ADAPTER_TABLE DB 54,54,54,54,54,54,54,25,00,00,00,00,00,20,20
- DB 24,20,48,16,48
- EQUIP_TABLE DB 16,16,32,32,32,32,32,48,00,00,00,00,00,16,16
- DB 48,16,32,32,32
-
- ;----------------------------------------------------------------------
- ; This is the main routine of the resident portion of the code
- ;----------------------------------------------------------------------
- SETMODE PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- CALL GET_CURS_ADDR ;Cursor address for this page
- PUSH ES:[BX] ;Save the cursor location
- MOV AL,ES:CRT_MODE ;Get current mode
- AND AL,01111111B ;Mask the high bit
- MOV MODE_SELECT,AL ;Store the initial video mode
-
- MOV GRAPH_TEXT,1
- MOV BX,7007H ;Colors for mono mode
- CMP AL,07H ;In mono text mode?
- JE NOT_COLOR_TEXT
- MOV BX,0503H ;Colors for graphics modes
- MOV GRAPH_TEXT,0
- CMP AL,3 ;In CGA text mode?
- JA NOT_COLOR_TEXT
- MOV GRAPH_TEXT,1
- MOV BH,ES:ACTIVE_PAGE
- MOV AH,8 ;Read current colors
- INT 10H ;BIOS read char/attribute
- MOV BL,AH ;Foreground color
- MOV BH,AH ;Background color
- XOR BH,1110111B ;Flip the color bits
- NOT_COLOR_TEXT:
- MOV COLORS,BX
- MOV DI,OFFSET WINDOW_BUFFER
- MOV DL,ES:COLUMNS ;Compute center of screen
- SUB DL,40 ;We'll use 40 columns
- SHR DL,1 ;Divide by two
- MOV LEFT_SIDE,DL ;This is column for left edge
-
- XOR DH,DH ;First window in row 0
- MOV COUNTER1,1
- CALL OPEN_WINDOW ;Open top window
- MOV COUNTER1,6
- CALL OPEN_WINDOW ;Open middle window
- MOV COUNTER1,3
- CALL OPEN_WINDOW ;Open bottom window
- MOV SI,OFFSET WINDOW_TEXT
- TEXT_LOOP:
- LODSW ;Fill in window text
- OR AL,AL
- JZ TEXT_DONE ;Is this the last string yet?
- MOV DX,AX ;Get row/column for this string
- ADD DL,LEFT_SIDE ;Add in left edge of window
- CALL TTY_STRING ;Put up the string
- JMP TEXT_LOOP ;Loop for all text strings
- TEXT_DONE:
- CMP ES:CRT_MODE,19 ;Is this mode 0-19?
- JA GET_A_KEY ;If not, can't point to it
- CALL VIDEO_COLUMN ;Get column for current mode
- INC DL
- MOV DH,16
- MOV AL,30 ;ASCII for up carrot
- CALL DISPLAY_NORMAL ;Pointer to current mode
- GET_A_KEY:
- CALL SHOW_PORTS ;Display comm port status
- CALL SHOW_MODE ;Display video info
- MOV CH,INVERSE
- CALL REV_BAR ;Inverse video for selected item
- XOR AH,AH
- INT 16H ;Read a keystroke
- PUSH AX ;Save the keystroke
- MOV CH,NORMAL
- CALL REV_BAR ;Turn off reverse bar
- POP AX ;Get back the keystroke
-
- CMP AH,48H ;Is it up arrow ?
- JNE NOT_UP
- CMP WORD PTR ES:[0000],0 ;Is there a COMM1?
- JZ GET_A_KEY ;If not, don't go up
- DEC ITEM_SELECT ;Move up to next item
- JNS GET_A_KEY
- MOV ITEM_SELECT,4
- JMP GET_A_KEY ;And get another keystroke
- NOT_UP:
- CMP AH,50H ;Is it down arrow?
- JNE NOT_DOWN
- INC ITEM_SELECT ;Move down to next item
- CMP ITEM_SELECT,4
- JBE GET_A_KEY
- MOV ITEM_SELECT,0
- JMP GET_A_KEY
- NOT_DOWN:
- CMP AH,4DH ;Is it right arrow?
- JNE NOT_RIGHT
- MOV AL,1 ;Indicate moving to right
- CALL SIDEWAYS ;And move the bar
- NOT_RIGHT:
- CMP AH,4BH ;Is it left arrow?
- JNE NOT_LEFT
- MOV AL,-1 ;Indicate moving to left
- CALL SIDEWAYS ;And move the bar
- NOT_LEFT:
- CMP AL,"+" ;Is it the plus key?
- JNE NOT_PLUS
- MOV CL,1 ;Indicate increasing value
- JMP CHG_COMM
- NOT_PLUS:
- CMP AL,"-" ;Is it the minus key?
- JNE NOT_MINUS
- MOV CL,-1 ;Indicate decrease value
- JMP CHG_COMM
- NOT_MINUS:
- CMP AH,1 ;Is it escape?
- JE ESC_OUT
- CMP AL,13 ;Is it carriage return?
- JE EXIT_OUT
- JMP GET_A_KEY ;Ignore any other keys
- ESC_OUT:
- MOV AL,ES:CRT_MODE ;Get starting video mode
- MOV MODE_SELECT,AL ;Make it the selected mode
- EXIT_OUT:
- XOR DH,DH ;Restore the window
- MOV SI,OFFSET WINDOW_BUFFER
- ROW_LOOP:
- MOV CX,40 ;Do all 40 columns
- MOV DL,LEFT_SIDE
- COL_LOOP:
- LODSW
- CALL DISPLAY_CHAR
- LOOP COL_LOOP ;Loop for each column
- INC DH ;Move to next row
- CMP DH,18
- JNE ROW_LOOP ;Loop for each row
- CALL GET_CURS_ADDR ;Get cursor address for this page
- POP ES:[BX] ;Restore original cursor position
-
- MOV BL,MODE_SELECT ;Get starting video mode
- CMP BL,ES:CRT_MODE ;Has it changed?
- JE SAME_MODE ;If not, just return
- XOR BH,BH
- MOV CL,EQUIP_TABLE[BX]
- MOV AX,ES:EQUIP_FLAG
- AND AL,11001111B ;Erase old video settings
- OR AL,CL ;Set new video equipment bits
- MOV ES:EQUIP_FLAG,AX;Write new equipment word
- MOV AX,BX
- INT 10H ;Reinitialize video adapter
- MOV AH,2
- XOR DX,DX ;Put cursor at home
- XOR BH,BH ;For page zero
- INT 10H ;BIOS set cursor function
- SAME_MODE:
- RET
- SETMODE ENDP
-
- ;----------------------------------------------------------------------
- ; Sideways moves the moving bar left and right
- ;----------------------------------------------------------------------
- SIDEWAYS PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- CMP ITEM_SELECT,0 ;Doing video modes?
- JE CHG_MODE ;If yes then change the mode
- MOV BL,PORT_SELECT ;Get comm port number
- ADD BL,AL ;Move to next port
- MOV PORT_SELECT,BL
- CMP BL,3 ;Maximum of 3 ports
- JA SIDEWAYS
-
- XOR BH,BH
- SHL BX,1
- CMP WORD PTR ES:[BX],0 ;Is there a card installed?
- JZ SIDEWAYS ;If no card move to next
- RET
- CHG_MODE:
- CMP ADAPTER_FLAGS,0
- JE UNKNOWN_ADAPTER
- MOV BL,MODE_SELECT ;Get current mode
- ADD BL,AL ;Move to next one
- MOV MODE_SELECT,BL
- CMP BL,19 ;Last mode is number 19
- JA CHG_MODE
- XOR BH,BH
- MOV CL,ADAPTER_TABLE[BX]
- AND CL,ADAPTER_FLAGS ;Is this adapter installed?
- JZ CHG_MODE ;If not, use next mode
- UNKNOWN_ADAPTER:
- RET
- SIDEWAYS ENDP
-
- ;----------------------------------------------------------------------
- ; CHG_COMM changes the parameters of the serial ports
- ;----------------------------------------------------------------------
- CHG_COMM PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV BL,PORT_SELECT ;Look at current port
- XOR BH,BH
- SHL BX,1
- MOV DX,ES:[BX] ;Get the card address
- ADD DX,3 ;Point to line control
- MOV AH,ITEM_SELECT
- DEC AH ;Changing baudrate?
- JZ CHG_BAUD
- DEC AH ;Doing parity change?
- JZ CHG_PARITY
- DEC AH ;Changing data bits
- JZ CHG_DATA_BITS
- DEC AH ;Changing stop bits
- JZ CHG_STOP_BITS
- JMP GET_A_KEY
- CHG_BAUD:
- CALL READ_SET_BPS ;Read current baudrate
- CMP CL,1
- JNE LOWER_BAUD ;Going up?
- CMP BX,3 ;At 38400 bps?
- JNE SHIFT_DOWN
- INC BX ;This is to get 57600 bps
- SHIFT_DOWN:
- SHR BX,1 ;Divide by two for new rate
- OR BX,BX ;Is divisor zero yet?
- JNZ SET_NEW_BAUD
- MOV BX,384 ;Divisor for 300 bps
- JMP SHORT SET_NEW_BAUD
- LOWER_BAUD:
- SHL BX,1 ;Times two for new rate
- CMP BX,4 ;At 28800 bps?
- JNE SHIFT_UP
- DEC BX ;This is to get 38400 bps
- SHIFT_UP:
- CMP BX,384 ;At 300 bps yet?
- JBE SET_NEW_BAUD
- MOV BX,1 ;Set divisor to 1
- SET_NEW_BAUD:
- CALL READ_SET_BPS ;Set the new value
- JMP GET_A_KEY ;And get another keystroke
- CHG_PARITY:
- IN AL,DX ;Get current parity bits
- MOV BL,AL
- AND AL,11000111B ;Erase old parity bits
- SHR BL,1 ;Shift parity bits over
- SHR BL,1
- SHR BL,1
- CHG_AGAIN:
- ADD BL,CL ;Add in the change
- AND BL,00000111B
- TEST BL,00000001B
- JNZ PARITY_OK
- TEST BL,00000110B
- JNZ CHG_AGAIN ;Skip meaningless settings
- PARITY_OK:
- SHL BL,1 ;Move parity bits back left
- SHL BL,1
- SHL BL,1
- OR AL,BL ;Replace other starting bits
- JMP SHORT CHG_COMM_RET
- CHG_DATA_BITS:
- IN AL,DX ;Get line control register
- MOV AH,AL ;Save original line control
- AND AH,11111100B ;Mask out old data bits
- ADD AL,CL
- AND AL,00000011B ;These are the new data bits
- OR AL,AH ;Put back other starting bits
- JMP SHORT CHG_COMM_RET
- CHG_STOP_BITS:
- IN AL,DX ;Get line control register
- XOR AL,00000100B ;Toggle the stop bit flag
- CHG_COMM_RET:
- OUT DX,AL ;Set new line status
- JMP GET_A_KEY
- CHG_COMM ENDP
-
- ;----------------------------------------------------------------------
- ; REV_BAR turns the moving bar off and on
- ;----------------------------------------------------------------------
- BAR_SIZE DB 0,6,5,1,1
- REV_BAR PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV DH,ITEM_SELECT ;Get selected item
- OR DH,DH ;Are we in video mode row?
- JZ DOING_VIDEO ;If yes then use video bar
-
- MOV BL,DH ;BL has item number
- XOR BH,BH
- MOV CL,BAR_SIZE[BX] ;Get size of this bar
- ADD DH,5
- MOV AL,7
- MUL PORT_SELECT
- ADD AL,17
- SUB AL,CL
- ADD AL,LEFT_SIDE
- MOV DL,AL
- REV_LOOP:
- CALL READ_CHAR ;Read current char at this position
- MOV AH,CH ;Change the attribute
- CALL DISPLAY_CHAR ;Then write the character again
- DEC CL
- JNZ REV_LOOP
- DONT_SHOW_IT:
- RET
- DOING_VIDEO:
- CMP MODE_SELECT,19 ;Is this mode in normal range
- JA DONT_SHOW_IT ;If not, just skip it
- CALL VIDEO_COLUMN ;Find column for this mode
- MOV DH,15 ;Video is on row 15
- MOV CL,2 ;Size of bar is two columns
- JMP REV_LOOP
- REV_BAR ENDP
-
- ;----------------------------------------------------------------------
- ; VIDEO_COLUMN returns the column position for the selected video mode
- ;----------------------------------------------------------------------
- COLUMN_DATA DB 1,3,5,7,9,11,13,15,0,0,0,0,0,18,21,24,27,30,33,36
- VIDEO_COLUMN PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV BL,MODE_SELECT ;Get selected mode
- XOR BH,BH
- MOV DL,COLUMN_DATA[BX]
- ADD DL,LEFT_SIDE ;Add in column of left side
- RET
- VIDEO_COLUMN ENDP
-
- ;----------------------------------------------------------------------
- ; OPEN_WINDOW draws a box with the double line border
- ;----------------------------------------------------------------------
- OPEN_WINDOW PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:NOTHING
- OR DH,DH
- JZ TOP_LINE
- MOV AL," "
- MOV CX," "*256+" "
- CALL OPEN_LINE ;Open a blank line
- TOP_LINE:
- MOV AL,201
- MOV CX,187*256+205
- CALL OPEN_LINE ;Top line
- WIN_LOOP2:
- MOV AL,186
- MOV CX,186*256+" "
- CALL OPEN_LINE ;Middle lines
- DEC COUNTER1
- JNZ WIN_LOOP2
- MOV AL,200
- MOV CX,188*256+205
- CALL OPEN_LINE ;Bottom line
- RET
- OPEN_WINDOW ENDP
-
- ;----------------------------------------------------------------------
- ; OPEN_LINE is used by OPEN_WINDOW to create one row of the window
- ;----------------------------------------------------------------------
- OPEN_LINE PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV DL,LEFT_SIDE
- CALL SAVE_CHAR
- MOV COUNTER2,38
- MIDDLE_LOOP:
- MOV AL,CL
- CALL SAVE_CHAR
- DEC COUNTER2
- JNZ MIDDLE_LOOP
- MOV AL,CH
- CALL SAVE_CHAR
- INC DH
- RET
- OPEN_LINE ENDP
-
- ;----------------------------------------------------------------------
- ; SAVE_CHAR stores a character from the screen and displays a new char
- ;----------------------------------------------------------------------
- SAVE_CHAR PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- PUSH AX ;Save the new character
- CALL READ_CHAR ;Read the existing character
- CMP GRAPH_TEXT,1
- JE MODE_TEXT1
- MOV AH,NORMAL ;Use normal foreground color
- MODE_TEXT1:
- MOV DS:[DI],AX ;And store it in the buffer
- INC DI
- INC DI
- POP AX ;Get back new character
- CMP GRAPH_TEXT,1
- JE MODE_TEXT2
- TEST AL,10000000B ;Is this a high bit character
- JZ MODE_TEXT2 ;If not, just continue
- MOV AL,"*" ;If it is, reset it to "*"
- MODE_TEXT2:
- CALL DISPLAY_NORMAL ;Put up the new character
- RET
- SAVE_CHAR ENDP
-
- ;----------------------------------------------------------------------
- ; TTY_STRING displays an ASCII string terminated with a byte of zero
- ;----------------------------------------------------------------------
- TTY_STRING PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- LODSB
- OR AL,AL
- JZ TTY_RET
- CALL DISPLAY_NORMAL
- JMP TTY_STRING
- TTY_RET:
- RET
- TTY_STRING ENDP
-
- ;----------------------------------------------------------------------
- ; DISPLAY routines display a character using a BIOS function call
- ;---------------------------------------------------------------------
- DISPLAY_NORMAL PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV AH,NORMAL
- DISPLAY_CHAR:
- PUSH BX
- PUSH CX
- CALL GET_CURS_ADDR ;Get address of BIOS cursor
- MOV ES:[BX],DX ;Tell BIOS where the cursor is
- MOV BL,AH ;Get back the attribute
- MOV BH,ES:ACTIVE_PAGE ;Get active page
- MOV CX,1 ;Write 1 character
- MOV AH,9 ;Write character and attribute
- INT 10H
- POP CX
- POP BX
- INC DL ;Advance the cursor column
- RET ;Done writing the character
- DISPLAY_NORMAL ENDP
-
- ;----------------------------------------------------------------------
- ; READ_CHAR reads a character from the screen
- ;---------------------------------------------------------------------
- READ_CHAR PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- CALL GET_CURS_ADDR ;Get address of BIOS cursor
- MOV ES:[BX],DX ;Tell BIOS where the cursor is
- MOV BH,ES:ACTIVE_PAGE ;Get active page
- MOV AH,8 ;BIOS function to read character
- INT 10H ;Read the character/attribute
- RET
- READ_CHAR ENDP
-
- ;----------------------------------------------------------------------
- ; GET_CURS_ADDR finds the address of the cursor for current video page
- ;---------------------------------------------------------------------
- GET_CURS_ADDR PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV BL,ES:ACTIVE_PAGE ;Get the current page number
- XOR BH,BH ;Convert to a word offset
- SHL BX,1 ;Times two for a word
- ADD BX,OFFSET CURSOR_POSN ;Add in base address
- RET
- GET_CURS_ADDR ENDP
-
- ;---------------------------------------------------------------------
- YES_TXT DB "Yes",0
- NO_TXT DB " No",0
- NA_TXT DB "n/a",0
- NONE_TXT DB " None",0
- ODD_TXT DB " Odd",0
- EVEN_TXT DB " Even",0
- SPACE_TXT DB "Space",0
- MARK_TXT DB " Mark",0
- PARITY_TABLE DW OFFSET ODD_TXT, OFFSET EVEN_TXT
- DW OFFSET SPACE_TXT, OFFSET MARK_TXT
-
- ;----------------------------------------------------------------------
- ; SHOW_PORTS displays the current settings of all comm ports
- ;----------------------------------------------------------------------
- SHOW_PORTS PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- XOR BX,BX
- MOV COUNTER1,BL ;Start with first comm port
- PORT_LOOP:
- MOV AL,7 ;Seven columns per port column
- MUL BL
- SHR AL,1
- MOV CX,6*256+16 ;Row/column for first item
- ADD CL,LEFT_SIDE ;Add in column of left edge
- ADD CL,AL ;And shift over to correct column
-
- MOV DX,ES:[BX] ;Retrive the comm port address
- MOV BP,DX ;And save it here
- OR DX,DX ;Is there a card installed?
- JNZ GOT_CARD ;If yes, display its status
- MOV SI,OFFSET NA_TXT
- MOV DX,CX ;Get row/column for this entry
- SUB DL,2
- CALL TTY_STRING ;Display "n/a" text
- JMP NEXT_PORT ;And go on to next port
- GOT_CARD:
- MOV AL,"0" ;Put a zero in bps column
- MOV DX,CX
- CALL DISPLAY_NORMAL ;Display the zero
- MOV DX,BP
- ADD DX,3 ;Point to line control register
- CALL READ_SET_BPS ;Read the current baud rate
- PUSH BX ;Save it
- CALL READ_SET_BPS ;Restore original baud settings
- POP BX ;Now we have the bps in BX
- OR BX,BX ;Is it set to zero?
- JZ NO_BPS_SET ;If yes, just skip it
- XOR DX,DX
- MOV AX,11520
- DIV BX
-
- MOV COUNTER2,6 ;Display five digits
- PUSH CX
- MOV SI,CX ;Save cursor position
- MOV BX,10
- MOV DX,AX
- XOR AX,AX
- CHAR_LOOP:
- MOV CX,DX
- XOR DX,DX
- DIV BX
- XCHG AX,CX
- DIV BX
- XCHG AX,DX
- ADD AL,"0" ;Convert this digit to ASCII
- PUSH DX
- DEC SI ;Backup cursor position
- MOV DX,SI
- CALL DISPLAY_NORMAL ;Display this digit
- DEC COUNTER2
- POP DX
- MOV AX,CX
- OR CX,DX
- JNZ CHAR_LOOP
- MOV DX,SI
- FILL_BLANKS:
- DEC DL
- MOV AL," "
- CALL DISPLAY_NORMAL
- DEC DL
- DEC COUNTER2
- JNZ FILL_BLANKS
- POP CX
- NO_BPS_SET:
- MOV DX,BP ;Get back the port address
- ADD DX,3 ;Line control register
- IN AL,DX
- PUSH AX ;Save starting status
- MOV SI,OFFSET NONE_TXT
- TEST AL,00001000B ;Look at parity enable bit
- JZ NO_PARITY
- AND AX,00110000B ;Look at parity bits
- SHR AX,1
- SHR AX,1
- SHR AX,1
- MOV SI,AX
- MOV SI,PARITY_TABLE[SI]
- NO_PARITY:
- MOV DX,CX
- SUB DL,4
- ADD DH,1
- CALL TTY_STRING ;Display parity status
-
- POP AX
- PUSH AX ;Get line control status again
- AND AL,00000011B ;Look at data bits
- ADD AL,35H ;Convert it to ASCII code
- MOV DX,CX
- ADD DH,2
- CALL DISPLAY_NORMAL
-
- POP DX
- PUSH DX ;Get line control status again
- MOV AL,"1" ;Assume one stop bit
- TEST DL,00000100B ;Are two stop bits used?
- JZ ONE_STOP
- INC AL
- ONE_STOP:
- MOV DX,CX
- ADD DH,3
- CALL DISPLAY_NORMAL
-
- MOV DX,BP
- ADD DX,6 ;Point to modem status register
- IN AL,DX
- MOV SI,OFFSET NO_TXT
- TEST AL,00100000B ;Is bit five set?
- JZ NO_DSR ;If not, DSR is not on
- MOV SI,OFFSET YES_TXT
- NO_DSR:
- MOV DX,CX
- ADD DH,4
- SUB DL,2
- CALL TTY_STRING
-
- POP AX
- MOV DX,BP ;Get back the card adress
- ADD DX,3
- OUT DX,AL ;Restore the line status register
- NEXT_PORT:
- MOV BL,COUNTER1
- XOR BH,BH
- INC BX
- INC BX
- CMP BL,8 ;Do four comm ports
- JAE PORT_DONE
- MOV COUNTER1,BL
- JMP PORT_LOOP
- PORT_DONE:
- RET
- SHOW_PORTS ENDP
-
- ;----------------------------------------------------------------------
- ; READ_SET_BPS reads the current baud rate and sets a new one
- ;----------------------------------------------------------------------
- READ_SET_BPS PROC NEAR
- ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING
- IN AL,DX ;Read the line status register
- MOV AH,AL ;Save initial line status
- MOV AL,80H
- OUT DX,AL
- SUB DX,3 ;Get to low byte of divisor
- IN AL,DX
- XCHG BL,AL
- OUT DX,AL ;Write the high byte of divisor
- INC DX ;Get to high byte of divisor
- IN AL,DX
- XCHG BH,AL
- OUT DX,AL ;Write the high byte of divisor
- INC DX ;Back to line status register
- INC DX
- MOV AL,AH ;Get back original line status
- OUT DX,AL ;And restore it
- RET
- READ_SET_BPS ENDP
-
- ;----------------------------------------------------------------------
- COLOR_TABLE DB 1,2,1,2,2,1,1,3,2,2,3,2,1,2,2
- RES_TABLE DW OFFSET RES_1, OFFSET RES_1, OFFSET RES_2
- DW OFFSET RES_2, OFFSET RES_3, OFFSET RES_3
- DW OFFSET RES_4, OFFSET RES_2, OFFSET RES_5
- DW OFFSET RES_4, OFFSET RES_6, OFFSET RES_6
- DW OFFSET RES_7, OFFSET RES_7, OFFSET RES_5
- RES_1 DB "25x40 ",0
- RES_2 DB "25x80 ",0
- RES_3 DB "320x200",0
- RES_4 DB "640x200",0
- RES_5 DB "320x200",0
- RES_6 DB "640x350",0
- RES_7 DB "640x480",0
- TEXT_TXT DB "Text ",0
- GRAPH_TXT DB "Graph",0
- COLOR_TXT DB "Color",0
- MONO_TXT DB "Mono ",0
- BW_TXT DB "B/W ",0
-
- ;----------------------------------------------------------------------
- ; SHOW_MODE displays the selected video mode number and resolution
- ;----------------------------------------------------------------------
- SHOW_MODE PROC NEAR
- ASSUME CS:CSEG, DS:CSEG, ES:BIOS_SEG
- MOV BL,MODE_SELECT ;Get selected mode
- MOV DH,14 ;Put text on row 14
- MOV DL,LEFT_SIDE
- ADD DL,9
-
- MOV AL,BL ;Current mode into AL
- MOV CL,10
- XOR AH,AH
- DIV CL ;Divide by 10
- MOV BH,AH ;Save remainder for next digit
- OR AL,AL ;Is first digit a zero?
- JNZ TWO_DIGITS ;If not, display it normally
- MOV AL," " - "0" ;Make first digit a space
- TWO_DIGITS:
- ADD AL,"0" ;Convert digit to ASCII
- CALL DISPLAY_NORMAL ;First digit of mode number
- MOV AL,BH
- ADD AL,"0"
- CALL DISPLAY_NORMAL ;Second digit of mode number
- CMP BL,19 ;Is this mode in table?
- JA NOT_IN_TABLE
- ADD DL,3 ;Skip three spaces
- XOR BH,BH
- MOV SI,OFFSET TEXT_TXT
- CMP BL,7
- JE TEXT_MODE
- JB NOT_EGA_MODE
- SUB BL,5
- NOT_EGA_MODE:
- CMP BL,3
- JBE TEXT_MODE
- MOV SI,OFFSET GRAPH_TXT
- TEXT_MODE:
- CALL TTY_STRING ;Show text/graph mode
- INC DL ;Skip a space
- MOV AL,COLOR_TABLE[BX]
- MOV SI,OFFSET BW_TXT
- DEC AL
- JZ SHOW_COLOR
- MOV SI,OFFSET COLOR_TXT
- DEC AL
- JZ SHOW_COLOR
- MOV SI,OFFSET MONO_TXT
- SHOW_COLOR:
- CALL TTY_STRING ;Show color/bw mode selected
- INC DL ;Skip a space
- SHL BX,1
- MOV SI,RES_TABLE[BX]
- CALL TTY_STRING ;Display resolution of this mode
- NOT_IN_TABLE:
- RET
- SHOW_MODE ENDP
-
- ;----------------------------------------------------------------------
- ; Interrupt 09 routine. watch for trigger key to pop up.
- ;----------------------------------------------------------------------
- NEWINT09 PROC FAR
- ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING
- STI ;Allow other interrupts
- PUSHF
- PUSH AX ;Must save processor state
- IN AL,60H ;Get the scan code
- CMP AL,HOTKEY ;Is it the hot key?
- JE TRIGGER ;If yes, check the mask
- INT09_EXIT: POP AX ;Restore the processor state
- POPF
- JMP CS:OLDINT09 ;Continue with ROM routine
- TRIGGER: MOV AH,2 ;Get keyboard status
- INT 16H ;BIOS keyboard service
- AND AL,0FH ;Test only for shift keys
- CMP AL,SHIFT_MASK ;Does it match out combination?
- JNE INT09_EXIT ;If not, ignore it
- CMP CS:BUSY_FLAG,0 ;Is SETMODE already active?
- JNZ INT09_EXIT ;If active, then exit
- INC CS:BUSY_FLAG ;Its active now
-
- IN AL,61H ;These instructions reset KB
- MOV AH,AL
- OR AL,80H
- OUT 61H,AL
- MOV AL,AH
- JMP SHORT KB_DELAY
- KB_DELAY:
- OUT 61H,AL
- CLI
- MOV AL,20H
- OUT 20H,AL ;Reset the interrupt controller
- STI
-
- PUSH BX ;Must preserve all registers
- PUSH CX
- PUSH DX
- PUSH BP
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS ;Set DS to CSEG
- MOV AX,BIOS_SEG ;ES points to BIOS data area
- MOV ES,AX
- ASSUME DS:CSEG, ES:BIOS_SEG
- CALL SETMODE ;Do the window
- DEC BUSY_FLAG
- POP ES ;Restore all registers
- POP DS
- ASSUME DS:NOTHING, ES:NOTHING
- POP DI
- POP SI
- POP BP
- POP DX
- POP CX
- POP BX
- POP AX
- POPF
- IRET ;Now were all done
- NEWINT09 ENDP
-
- ;--------------------------------------------------------------------
- ; Here is the code used to initialize setmode
- ;--------------------------------------------------------------------
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
- EVEN ;Align the buffer
- WINDOW_BUFFER LABEL BYTE
- INITIALIZE:
- MOV DX,OFFSET COPYRIGHT ;Do first half of copyright
- MOV AH,9
- INT 21H
-
- MOV AX,1A00H ;Read display combination code
- INT 10H
- CMP AL,1AH ;Is VGA or MCGA present?
- JNE NO_VGA
- MOV AH,00100000B ;Set bit for MCGA adapter
- CMP BL,0BH ;Is it model 30 with mono?
- JE SET_BITS
- CMP BL,0CH ;Is it model 30 with color?
- JE SET_BITS
- MOV AH,00010000B ;Set bit for VGA adapter
- CMP BL,7 ;Is it VGA mono?
- JE SET_BITS
- CMP BL,8 ;Is it VGA color?
- JE SET_BITS
- NO_VGA:
- XOR DH,DH
- MOV AH,0B8H ;Look for a color adapter
- CALL LOOK_FOR_CARD
- JNE NO_COLOR
- OR DH,00000010B ;Set bit for color adapter
- NO_COLOR:
- MOV AH,0B0H ;Look for mono adapter
- CALL LOOK_FOR_CARD
- JNE NO_MONO
- OR DH,00000001B ;Set bit for mono adapter
- NO_MONO:
- MOV ADAPTER_FLAGS,DH
- MOV AH,12H
- MOV BL,10H ;BIOS get EGA info function
- INT 10H
- CMP BL,10H ;Did BL change?
- JE NOT_EGA ;If not, no EGA present
-
- PUSH ES
- MOV AX,BIOS_SEG
- MOV ES,AX
- ASSUME ES:BIOS_SEG
- MOV AH,00000100B ;Set bit for EGA color
- TEST ES:EGA_INFO,00000010B ;Is an EGA mono attached?
- POP ES
- ASSUME ES:CSEG
- JZ SET_BITS
- MOV AH,00001000B ;Set bit for EGA mono only
- SET_BITS:
- OR ADAPTER_FLAGS,AH
- NOT_EGA:
- ; Search for an previously installed copy of setmode
- NOT BYTE PTR START ;Modify to avoid false match
- XOR BX,BX ;Start search at segment zero
- MOV AX,CS ;Compare to this code segment
- NEXT_SEGMENT:
- INC BX ;Look at next segment
- CMP AX,BX ;Until reaching this code segment
- MOV ES,BX
- JE NOT_INSTALLED
- MOV SI,OFFSET START ;Setup to compare strings
- MOV DI,SI
- MOV CX,16 ;16 bytes must match
- REP CMPSB ;Compare DS:SI to ES:DI
- OR CX,CX ;Did the strings match?
- JNZ NEXT_SEGMENT ;If no match, try next segment
- MOV DX,OFFSET INSTALLED_MSG
- ERR_EXIT: MOV AH,9 ;DOS display string service
- INT 21H ;Display error message
- MOV AX,4C01H ;Return error code
- INT 21H ;Exit to DOS
- NOT_INSTALLED:
- ASSUME ES:NOTHING
- MOV AX,3509H ;Get keyboard vector
- INT 21H
- MOV WORD PTR [OLDINT09], BX ;Save segment
- MOV WORD PTR [OLDINT09+2],ES ;Save offset
- MOV DX,OFFSET NEWINT09
- MOV AX, 2509H
- INT 21H ;DOS function to change vector
-
- ;----------------------------------------------------------------------
- ; Deallocate our copy of the enviornment. Terminate
- ; and stay resident. Leave code and space for buffer resident.
- ;----------------------------------------------------------------------
-
- MOV AX,DS:[002CH] ;Get segnemt of enviornment
- MOV ES,AX ;Put it into ES
- MOV AH,49H ;Release allocated memory
- INT 21H
- MOV DX,OFFSET WINDOW_BUFFER + 40*18*2 + 15
- MOV CL,4 ;Shift four to divide by 16
- SHR DX,CL ;Convert size to paragraphs
- MOV AX,3100H ;Return success status
- INT 21H
-
- ;---------------------------------------------------------------------
- ; This routine examines memory to look for a display card.
- ;---------------------------------------------------------------------
- LOOK_FOR_CARD PROC NEAR
- ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING
- XOR SI,SI ;Look at offset zero
- PUSH DS
- XOR AL,AL
- MOV DS,AX ;Load the segment register
- MOV CH,[SI] ;Store the initial value
- MOV AL,55H
- MOV [SI],AL ;Write pattern of ones and zeros
- JMP SHORT DELAY ;A short delay
- DELAY:
- MOV AH,[SI] ;Read the byte we just wrote
- MOV [SI],CH ;Restore the initial value
- POP DS
- CMP AL,AH ;Did it match?
- RET
- LOOK_FOR_CARD ENDP
- CSEG ENDS
- END START
-